package moltencore.game.loader;

import moltencore.config.Config;
import moltencore.game.*;
import moltencore.game.bubble.BubbleRandomizer;
import moltencore.game.collision.HorizontalLine;
import moltencore.game.collision.ICollidable;
import moltencore.game.collision.VerticalLine;
import moltencore.game.loader.exception.FieldCreationException;
import moltencore.game.loader.exception.GameCreationException;
import spark.exception.LoadingException;
import spark.math.Vector2;
import spark.utility.DecrementalShortIdFactory;
import spark.utility.IncrementalLongIdFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;

public class GameCreator {
	public static Game createGame(Settings settings, long hostIdentification) throws GameCreationException {
		Game game = null;
		switch(settings.getMode()) {
			case DeathMatch:
				game = new GameDeathmatch(hostIdentification);
				break;
			case TimeAttack:
				game = new GameTimeattack(hostIdentification);
				break;
			case ShootEmUp:
				game = new GameShootEmUp(hostIdentification);
				break;
			default:
				throw new GameCreationException("Invalid game mode: " + settings.getMode());
		}
		return game;
	}

	public static Collection<Field> createFields(Settings settings) throws FieldCreationException {
		BubbleRandomizer bubbleRandomizer = new BubbleRandomizer(
				settings.getOrdinaryBubbleCount(),
				settings.getOrdinaryBubbleProbability(),
				settings.getRainbowBubbleProbability(),
				settings.getGhostBubbleProbability(),
				settings.getBlazingBubbleProbability());
		DecrementalShortIdFactory bubbleIdFactory = new DecrementalShortIdFactory((short) -1);
		IncrementalLongIdFactory fieldIdFactory = new IncrementalLongIdFactory();
		GridGenerator gridGenerator = new GridGenerator();
		String fieldFile = settings.isTeamsEnabled() ? "doubleField.bbl" : "singleField.bbl";
		Level level = null;
		try {
			level = LevelLoader.loadLevel(Config.getInstance().getLevelsPath() + "/" + fieldFile, new LevelParser());
		}
		catch(LoadingException e) {
			throw new FieldCreationException("Could not find server side game level file", e);
		}
		gridGenerator.generateGrid(bubbleRandomizer, level, bubbleIdFactory);

		int fieldsToCreate = settings.getPlayerLimit() / settings.getTeamSize();
		ArrayList<Field> gameFields = new ArrayList<Field>(settings.getPlayerLimit());
		for(int i = 0; i < fieldsToCreate; i++) {
			ArrayList<ICollidable> collidables = new ArrayList<ICollidable>();
			for(HorizontalLine horizontalLine : level.getHorizontalLines()) {
				collidables.add(new HorizontalLine(horizontalLine.getYPosition(), horizontalLine.isSticky()));
			}
			for(VerticalLine verticalLine : level.getVerticalLines()) {
				collidables.add(new VerticalLine(verticalLine.getXPosition(), verticalLine.isSticky()));
			}
			ArrayList<ICollidable> criticalAreas = new ArrayList<ICollidable>();
			for(HorizontalLine horizontalLine : level.getCriticalAreas()) {
				criticalAreas.add(new HorizontalLine(horizontalLine.getYPosition(), false));
			}
			ArrayList<ICollidable> restrictedAreas = new ArrayList<ICollidable>();
			for(HorizontalLine horizontalLine : level.getRestrictedAreas()) {
				restrictedAreas.add(new HorizontalLine(horizontalLine.getYPosition(), false));
			}
			Field field = new Field(
					fieldIdFactory.getNextId(), fieldFile,
					settings.getCriticalMass(), settings.isWind(), settings.isGravity(),
					gridGenerator.copyLastGenerated(), level.getPushBubbles(),
					new BubbleRandomizer(bubbleRandomizer),
					collidables, restrictedAreas, criticalAreas, level.getCannonData(), settings.getPushCount(),
					settings.getMode().getPushType());
			gameFields.add(field);
		}
		return gameFields;
	}
}
